package com.xhy.documents_collection.service.task.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xhy.documents_collection.entity.VO.TaskRecordVO;
import com.xhy.documents_collection.enums.ServiceType;
import com.xhy.documents_collection.holder.UserHolder;
import com.xhy.documents_collection.cache.UserCache;
import com.xhy.documents_collection.entity.DO.FileDO;
import com.xhy.documents_collection.entity.DO.UploadDO;
import com.xhy.documents_collection.entity.PO.log.SysLog;
import com.xhy.documents_collection.entity.PO.task.Task;
import com.xhy.documents_collection.entity.PO.task.TaskRecord;
import com.xhy.documents_collection.entity.PO.task.TaskUser;
import com.xhy.documents_collection.entity.PO.team.Team;
import com.xhy.documents_collection.entity.PO.team.TeamUser;
import com.xhy.documents_collection.mapper.task.TaskMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xhy.documents_collection.service.async.AsyncService;
import com.xhy.documents_collection.service.task.TaskRecordService;
import com.xhy.documents_collection.service.task.TaskService;
import com.xhy.documents_collection.service.task.TaskTimingRecordService;
import com.xhy.documents_collection.service.task.TaskUserService;
import com.xhy.documents_collection.service.team.TeamService;
import com.xhy.documents_collection.service.team.TeamUserService;
import com.xhy.documents_collection.utils.R;
import com.xhy.documents_collection.utils.Template;
import com.xhy.documents_collection.utils.TransitionByteToCH;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author xhy
 * @since 2022-11-14
 */
@Service
public class TaskServiceImpl extends ServiceImpl<TaskMapper, Task> implements TaskService {

    @Resource
    private TeamService teamService;

    @Resource
    private TaskRecordService taskRecordService;

    @Resource
    private TeamUserService teamUserService;

    @Resource
    private TaskUserService taskUserService;

    @Resource
    private AsyncService asyncService;

    @Resource
    TaskTimingRecordService taskTimingRecordService;


    private R verifyGroup(Task task){

        // TODO 组队功能待完善
        if (task.getGroupUserLimit() != 0){
            return R.error().message("组队功能有缺陷...正在完善...");
        }

        if (task.getGroupUserLimit()!=0 && task.getIsGroup()!=1){
            return R.error().message("请选择可组队");
        }
        // 组队人数限制不能超过团队人数
        int userCount = teamUserService.count(new QueryWrapper<TeamUser>().eq("t_id", task.getTId()));
        task.setGroupUserLimit(task.getGroupUserLimit() == null ? 0 : task.getGroupUserLimit());
        if (task.getGroupUserLimit() > userCount){
            return R.error().message("组队人数不可超过团队人数");
        }
        return R.ok();
    }

    @Override
    @Transactional
    public R issueTask(Task task) {

        R r = verifyGroup(task);
        if (!r.getState()){
            return r;
        }

        // 团队中任务名称不可重复
        int count = count(new LambdaQueryWrapper<Task>().eq(Task::getTId, task.getTId()).eq(Task::getName, task.getName()));
        if (count == 1){
            return R.error().message("任务名称已存在");
        }
        // 校验模板
        if (!Template.verify(task.getFileNameTemplate())){
            return R.error().message("模板有误,请检查模板");
        }

        Integer teamId = task.getTId();
        Integer uId = UserHolder.get();
        task.setUId(uId);



        try {
            count = teamService.count(new QueryWrapper<Team>().eq("u_id",uId).eq("id",teamId));
            if (count == 0){
                return r.message("主键不可重复");
            }
             save(task);
            // 根据团队创建任务记录
            ArrayList<TaskRecord> taskRecords = new ArrayList<>();
            ArrayList<TaskUser> taskUsers = new ArrayList<>();
            Integer taskId = task.getId();
            teamUserService.list(new QueryWrapper<TeamUser>().eq("t_id", teamId).select("u_id")).stream()
                    .forEach(user->{
                        TaskRecord taskRecord = new TaskRecord();
                        taskRecord.setTId(taskId);
                        taskRecord.setUId(user.getUId());
                        taskRecord.setGroupUserId(String.valueOf(user.getUId()));
                        TaskUser taskUser = new TaskUser();
                        taskUser.setTId(taskId);
                        taskUser.setUId(user.getUId());
                        taskUsers.add(taskUser);
                        taskRecords.add(taskRecord);
                    });
            taskUserService.saveBatch(taskUsers);
            taskRecordService.saveBatch(taskRecords);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return r.message("发布失败");
        }
        if(!task.getFile().isEmpty()){
            try {
                MultipartFile file = task.getFile();
                UploadDO uploadDO = new UploadDO();
                uploadDO.setTaskId(task.getId());
                uploadDO.setUId(uId);
                FileDO fileDO = new FileDO();
                fileDO.setFileName(file.getOriginalFilename());
                fileDO.setFileSize(file.getSize());
                fileDO.setInputStream(file.getInputStream());
                uploadDO.setFileDO(fileDO);
                asyncService.uploadTaskDescription(uploadDO);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return r.message("发布成功,如果上传作业描述请刷新界面预览");
    }

    @Override
    @Transactional
    public R deleteTasks(List<Integer> taskIds) {
        if (ObjectUtils.isEmpty(taskIds)){
            return R.error().message("请选择删除的任务");
        }

        Integer uId = UserHolder.get();

        List<String> filePaths = listByIds(taskIds).stream().filter(task -> !ObjectUtils.isEmpty(task.getFilePath())).map(Task::getFilePath).collect(Collectors.toList());
        List<String> taskNames = baseMapper.selectList(new QueryWrapper<Task>().in("id", taskIds).select("name"))
                .stream()
                .map(Task::getName)
                .collect(Collectors.toList());
        try {
            // 删除任务
            baseMapper.delete(new QueryWrapper<Task>().eq("u_id",uId).in("id",taskIds));
            // 删除任务下的所有记录
            taskRecordService.remove(new QueryWrapper<TaskRecord>().in("t_id",taskIds));
            // 删除任务用户中间表
            taskUserService.remove(new QueryWrapper<TaskUser>().in("t_id",taskIds));
            asyncService.deleteFiles(filePaths);
            taskTimingRecordService.removeTaskByIds(taskIds);
        }catch (Exception e){
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return R.error().message("删除失败");
        }
        return R.ok().message("删除成功");
    }

    @Resource
    private TaskMapper taskMapper;

    @Override
    public Integer getTeamIdByTaskId(Integer taskId) {

        return getById(taskId).getTId();
    }

    @Override
    public String getTaskName(Integer taskId) {

        return getById(taskId).getName();
    }

    @Override
    public Task get(Integer taskId) {
        return taskMapper.get(taskId);
    }

    @Override
    public R update(Task task) {
        R r = verifyGroup(task);
        if (!r.getState()){
            return r;
        }
        // 校验模板
        if (!Template.verify(task.getFileNameTemplate())){
            return R.error().message("模板有误,请检查模板");
        }
        task.setName(null);
        Integer uId = UserHolder.get();
        update(task,new QueryWrapper<Task>().eq("u_id", uId).eq("id",task.getId()));
        if(!task.getFile().isEmpty()){
            try {
                MultipartFile file = task.getFile();
                UploadDO uploadDO = new UploadDO();
                uploadDO.setTaskId(task.getId());
                FileDO fileDO = new FileDO();
                fileDO.setFileName(file.getOriginalFilename());
                fileDO.setInputStream(file.getInputStream());
                uploadDO.setFileDO(fileDO);
                asyncService.uploadTaskDescription(uploadDO);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return r.message("修改成功,如果上传作业描述请刷新界面预览");
    }

    @Override
    public R noSubmit() {

        Integer userId = UserHolder.get();
        // 查出用户未提交的任务
        List<Integer> taskRecordIds = taskRecordService.
                list(new LambdaQueryWrapper<TaskRecord>().select(TaskRecord::getTId).eq(TaskRecord::getUId, userId).eq(TaskRecord::getIsSubmit,false))
                .stream().map(TaskRecord::getTId).collect(Collectors.toList());
        if (ObjectUtils.isEmpty(taskRecordIds)){
            return R.ok().data("data", Collections.EMPTY_LIST);
        }
        // 筛选正在进行中的任务
        Map<Integer, Task> taskMap = listByIds(taskRecordIds).stream().filter(task -> new Date().before(task.getEndTime())).collect(Collectors.toMap(Task::getId, Task -> Task));

        if (ObjectUtils.isEmpty(taskMap)){
            return R.ok().data("data", Collections.EMPTY_LIST);
        }
        List<Integer> ids = taskMap.values().stream().map(Task::getId).collect(Collectors.toList());
        List<TaskRecordVO> result = taskRecordService.
                list(new LambdaQueryWrapper<TaskRecord>().in(TaskRecord::getTId, ids).eq(TaskRecord::getUId, userId))
                .stream().map(taskRecord -> {
                    TaskRecordVO taskRecordVO = new TaskRecordVO();
                    taskRecordVO.setId(taskRecord.getId());
                    taskRecordVO.setFileSizeString(TransitionByteToCH.getPrintSize(taskRecord.getFileSize()));
                    taskRecordVO.setIsSubmit(taskRecord.getIsSubmit());
                    taskRecordVO.setName(taskMap.get(taskRecord.getTId()).getName());
                    taskRecordVO.setSubmitTime(taskRecord.getSubmitTime());
                    taskRecordVO.setFileName(taskRecord.getFileName());
                    taskRecordVO.setUrl(taskMap.get(taskRecord.getTId()).getUrl());
                    return taskRecordVO;
                }).collect(Collectors.toList());


        return R.ok().data("data",result).count(result.size());
    }


}
